using GameServer.Common.Utils;
using System;
namespace GameServer.Common.Physics
{

    public class CollisionDetection
    {

        public static bool PointCircleIntersection(double radius, double circleCentreX, double circleCentreY, double pointX, double pointY)
        {
            if (radius >= Math2.GetDistance(circleCentreX, circleCentreY, pointX, pointY))
                return true;
            else
                return false;
        }

        public static bool CircleRectangleIntersection(double radius, double circleCentreX, double circleCentreY, double rectLeft, double rectTop, double rectRight, double rectBottom)
        {
            double rectWidth = rectRight - rectLeft;
            double rectHeight = rectBottom - rectTop;
            double rectCentreX = rectRight - rectWidth / 2.0;
            double rectCentreY = rectBottom - rectHeight / 2.0;
            double rectDiagonal = Math.Sqrt(rectWidth / 2.0 * rectWidth / 2.0 + rectHeight / 2.0 * rectHeight / 2.0);
            double distanceBetweenCentres = Math2.GetDistance(circleCentreX, circleCentreY, rectCentreX, rectCentreY);
            if (distanceBetweenCentres > rectDiagonal + radius)
                return false;
            //			var angleOfElevation_Degrees:Number = Math2.getAngleOfElevationDegree(rectCentreX, rectCentreY, circleCentreX, circleCentreY);
            double angleOfElevation_Degrees = Math2.ConvertTo360DegreeAngle(Math2.GetAngleOfElevationDegree(rectCentreX, rectCentreY, circleCentreX, circleCentreY));
            //			trace("Angle",angleOfElevation_Degrees, "cirCenX", circleCentreX, "cirCenY", circleCentreY);
            if (((angleOfElevation_Degrees == 0 || angleOfElevation_Degrees == 180) && (distanceBetweenCentres > rectWidth / 2.0 + radius)) ||
                ((angleOfElevation_Degrees == 90 || angleOfElevation_Degrees == 270) && (distanceBetweenCentres > rectHeight / 2.0 + radius)))
            {
                return false;
            }
            if ((angleOfElevation_Degrees == 45 || angleOfElevation_Degrees == 135 || angleOfElevation_Degrees == 225 || angleOfElevation_Degrees == 315)
                && distanceBetweenCentres < rectDiagonal + radius)
                return true;
            double oppSideLength;
            double rectBoundaryPointFX = 0;
            double rectBoundaryPointFY = 0;
            double tanOfAngleOfElevation = Math.Tan(Math2.ToRad(angleOfElevation_Degrees));
            double tanOfAngleOfElevation_OffVertical;

            //Potential point of intersection lies on rectangle's right side
            if (angleOfElevation_Degrees < 45)
            {
                oppSideLength = rectWidth / 2.0 * Math.Abs(tanOfAngleOfElevation);
                rectBoundaryPointFX = rectRight;
                rectBoundaryPointFY = rectBottom - rectHeight / 2.0 + oppSideLength;
                //				trace("tan", tanOfAngleOfElevation, "oppSid", oppSideLength, "rectBX", rectBoundaryPointFX, "rectBY", rectBoundaryPointFY);
            }
            if (angleOfElevation_Degrees > 315)
            {
                //			if(angleOfElevation_Degrees > -45){
                oppSideLength = rectWidth / 2.0 * Math.Abs(tanOfAngleOfElevation);
                rectBoundaryPointFX = rectRight;
                rectBoundaryPointFY = rectBottom - rectHeight / 2.0 - oppSideLength;
                //trace("3");
            }
            //Potential point of intersection lies on rectangle's left side
            if (angleOfElevation_Degrees > 135 && angleOfElevation_Degrees < 180)
            {
                oppSideLength = rectWidth / 2.0 * Math.Abs(tanOfAngleOfElevation);
                rectBoundaryPointFX = rectLeft;
                rectBoundaryPointFY = rectBottom - rectHeight / 2.0 + oppSideLength;
                //				trace("tan", Math.Abs(tanOfAngleOfElevation), "oppSid", oppSideLength, "rectBX", rectBoundaryPointFX, "rectBY", rectBoundaryPointFY);
                //trace("4");
            }
            if (angleOfElevation_Degrees > 180 && angleOfElevation_Degrees < 225)
            {
                oppSideLength = rectWidth / 2.0 * Math.Abs(tanOfAngleOfElevation);
                rectBoundaryPointFX = rectLeft;
                rectBoundaryPointFY = rectBottom - rectHeight / 2.0 - oppSideLength;
                //trace("5");
            }

            //Potential point of intersection lies on rectangle's bottom side
            if (angleOfElevation_Degrees > 45 && angleOfElevation_Degrees < 90)
            {
                tanOfAngleOfElevation_OffVertical = Math.Tan(Math2.ToRad(90 - angleOfElevation_Degrees));
                oppSideLength = rectHeight / 2.0 * Math.Abs(tanOfAngleOfElevation_OffVertical);
                rectBoundaryPointFX = rectRight - rectWidth / 2.0 + oppSideLength;
                rectBoundaryPointFY = rectBottom;
                //trace("6");
            }
            if (angleOfElevation_Degrees > 90 && angleOfElevation_Degrees < 135)
            {
                tanOfAngleOfElevation_OffVertical = Math.Tan(Math2.ToRad(angleOfElevation_Degrees - 90));
                oppSideLength = rectHeight / 2.0 * Math.Abs(tanOfAngleOfElevation_OffVertical);
                rectBoundaryPointFX = rectRight - rectWidth / 2.0 - oppSideLength;
                rectBoundaryPointFY = rectBottom;
                //trace("7");
            }
            //Potential point of intersection lies on rectangle's top side
            if (angleOfElevation_Degrees > 225 && angleOfElevation_Degrees < 270)
            {
                tanOfAngleOfElevation_OffVertical = Math.Tan(Math2.ToRad(270 - angleOfElevation_Degrees));
                oppSideLength = rectHeight / 2.0 * Math.Abs(tanOfAngleOfElevation_OffVertical);
                rectBoundaryPointFX = rectRight - rectWidth / 2.0 - oppSideLength;
                rectBoundaryPointFY = rectTop;
                //trace("8");
            }
            if (angleOfElevation_Degrees > 270 && angleOfElevation_Degrees < 315)
            {
                tanOfAngleOfElevation_OffVertical = Math.Tan(Math2.ToRad(angleOfElevation_Degrees - 270));
                oppSideLength = rectHeight / 2.0 * Math.Abs(tanOfAngleOfElevation_OffVertical);
                rectBoundaryPointFX = rectRight - rectWidth / 2.0 + oppSideLength;
                rectBoundaryPointFY = rectTop;
                //				trace("tan", Math.Abs(tanOfAngleOfElevation_OffVertical), "oppSid", oppSideLength, "rectBX", rectBoundaryPointFX, "rectBY", rectBoundaryPointFY);				
                //trace("9");
            }
            //			trace(angleOfElevation_Degrees);
            if (distanceBetweenCentres + radius < Math2.GetDistance(rectCentreX, rectCentreY, rectBoundaryPointFX, rectBoundaryPointFY))
                return true;
            //			trace(radius, circleCentreX, circleCentreY, rectBoundaryPointFX, rectBoundaryPointFY);
            return PointCircleIntersection(radius, circleCentreX, circleCentreY, rectBoundaryPointFX, rectBoundaryPointFY);
        }

        public static bool PointRectangleIntersection(double pointX, double pointY, double rectLeft, double rectTop, double rectRight, double rectBottom)
        {
            return (pointX <= rectRight && pointX >= rectLeft && pointY <= rectBottom && pointY >= rectTop);
        }
    }
}
